<?php

namespace System\library\utility;

use System\library\config\Config;
use System\library\utility\Tools;

/**
 * <b>Class</b> :        Validate<br>
 * <b>Fonction</b> :     Methodes utilitaires de validité
 * <br>
 * @version              1.0
 * @author               Dread <dreadlokeur@gmail.com>
 * @license              Licence publique générale GNU http://www.gnu.org/licenses/gpl.html
 * @copyright            Copyright 2011 - MidichloriansPHP and contributors
 * @package              System
 * @subpackage           library\utility
 */
class Validate {

    /**
     * Checks if the a variable is empty with remove white space if source is string
     * !!Important!! '0' or 0 is not considered to be empty !
     * @param Mixed $var
     * @return boolean
     */
    public static function isEmpty($var) {
        if ($var === null || is_string($var) && trim($var) === '' || is_array($var) && count($var) == 0)
            return true;
        return false;
    }

    /**
     * Checks if the number is an int, and can be check the range
     * @param Mixed $number
     * @param Integer $gt Check if greater than $gt
     * @param Integer $lt Check if lower than $lt
     * @return Boolean
     */
    public static function isInt($number, $gt = false, $lt = false) {
        if (is_string($number)) {
            if (trim($number) == '')
                return false;
            // Extract sign if exist
            $sign = '';
            if ($number[0] == '+' || $number[0] == '-') {
                $sign = $number[0];
                $number = substr($number, 1);
            }
            $number = ($sign == '-' ? '-' . $number : $number);
            if ($number !== (string) (int) $number)
                return false;
            $number = (int) $number;
        }elseif (((int) $number) !== $number)
            return false;
        if (!$lt && !$gt || $lt && $number <= $lt && $gt && $number >= $gt || !$lt && $gt && $number >= $gt || !$gt && $lt && $number <= $lt)
            return true;
        return false;
    }

    /**
     * Checks if the number is a float and if is in the range of the given values.
     *
     * @param Mixed $number Number to check
     * @param int $from Beginning of the range
     * @param int $to Ending of the range
     *
     * @return boolean
     */
    public static function isFloat($number, $gt = false, $lt = false) {
        if (is_string($number)) {
            if (trim($number) == '')
                return false;
            // Extract sign if exist
            $sign = '';
            if ($number[0] == '+' || $number[0] == '-') {
                $sign = $number[0];
                $number = substr($number, 1);
            }
            $number = ($sign == '-' ? '-' . $number : $number);
            if (!\is_numeric($number))
                return false;
            $number = (float) $number;
        }elseif (is_int($number)) {
            $number = (float) $number;
        }
        if (!\is_float($number))
            return false;
        if (!$lt && !$gt || $lt && $number <= $lt && $gt && $number >= $gt || !$lt && $gt && $number >= $gt || !$gt && $lt && $number <= $lt)
            return true;
        return false;
    }

    /**
     * Check if a var is a string and can be check the size of it
     * @param Mixed $data
     * @param Integer $minLenght
     * @param Integer $maxLenght
     */
    public static function isString($var, $minLenght = false, $maxLenght = false) {
        if (!is_string($var))
            return false;
        if ($minLenght && strlen($var) < $minLenght)
            return false;
        if ($maxLenght && strlen($var) > $maxLenght)
            return false;
        return true;
    }

    /**
     * Check if a string is a correct variable name
     * @param String $name
     * @return Boolean
     */
    public static function isVariableName($name) {
        if (!is_string($name))
            return false;
        return (boolean) preg_match('`^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$`', $name);
    }

    /**
     * Checks if the string is a well formed email address..
     *
     * @param string $string
     * @return boolean
     */
    public static function isEmail($email) {
        if (!\is_string($email) || strlen($email) > 255)
            return false;
        if (\ExFramework\Validate::phpVersionCompareTo('5.3.3') >= 0)
            return (boolean) filter_var($email, FILTER_VALIDATE_EMAIL);
        else
            return (boolean) preg_match('`^(?!\.)[.\w!#$%&\'*+/=?^_\`{|}~-]+@(?!-)[\w-]+\.\w+$`i', $email);
    }

    /**
     * Check if the variable is a representation of ip
     * @param String $ip
     * @param Boolean $allowIpV4 allow ipv4 (true by default)
     * @param Boolean $allowIpV6 allow ipv6 (true by default)
     * @return Boolean
     */
    public static function isIp($ip, $allowIpV4 = true, $allowIpV6 = true) {
        if ($allowIpV6 && $allowIpV4)
            return \filter_var($ip, FILTER_VALIDATE_IP) !== false;
        if (!$allowIpV6 && $allowIpV4)
            return \filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
        if ($allowIpV6 && !$allowIpV4)
            return \filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
    }

    /**
     * Check if a var is a url
     *
     * @access public
     * @static
     * @param <void>
     * @return <bool>
     */
    public static function isUrl($value) {
        return (bool) (preg_match("#https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?#", $value));
    }

    /**
     * Permet de verifier si un fichier est de mimetype voulut
     *
     * @access public
     * @static
     * @param <string> $mimetype: le mimetype voulut
     * @param <string> $file: le fichier
     * @return <bool>
     */
    public static function isFileMimeTye($mimetype, $file) {
        if (!extension_loaded('fileinfo'))
            throw new \Exception('fileinfo extension not loaded try change your PHP configuration');

        if (!is_file(realpath($file)) || !file_exists(realpath($file)) || !is_readable(realpath($file)))
            throw new \Exception('La vérification du mimetype du fichier "' . $file . '" à échoué, le fichier n\'existe pas ou est invalid');

        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        return (strpos($finfo->file(realpath($file)), $mimetype) !== false) ? true : false;
    }

    /**
     * Permet de verifier si un fichier est de type voulut, depuis son extension dans son nom (.type)
     *
     * @access public
     * @static
     * @param <string> $type: le type voulut
     * @param <string> $file: le nom du fichier
     * @return <bool>
     */
    public static function isFileType($type, $file) {
        return (str_replace('.', '', strrchr($file, '.')) != $type) ? false : true;
    }

    /**
     * Permet de verifier si un string fait entre 4 et 16 caractere et est valid : verification d'un pseudo
     *
     * @access public
     * @static
     * @param <string> $value
     * @return <bool>
     *
     * TODO add validation rule
     */
    public static function isValidPseudo($value) {
        return (bool) (preg_match("#^[A-Za-z][0-9A-Za-z_-]{2,14}[0-9A-Za-z_-]$#", $value));
    }

    /**
     * Permet de verifier si un string fait entre 4 et 16 caractere et est valid: verification d'un password
     *
     * @access public
     * @static
     * @param <void>
     * @return <bool>
     *
     * TODO add validation rule
     */
    public static function isValidPassword($value) {
        return (bool) (preg_match("#^[A-Za-z][0-9A-Za-z_-]{2,14}[0-9A-Za-z_-]$#", $value));
    }

    /**
     * Permet de verifier si une email est une mail bannis dans la liste de wanted_email
     *
     * @access public
     * @static
     * @param <void>
     * @return <bool>
     */
    public static function isWantedEmail($value, $file = null) {
        //On prend la valeur après le "@"
        preg_match('/[^@]+$/', $value, $matches);
        if ($file !== null) {
            if (!file_exists($file))
                throw new \Exception('file don\'t exists');
            $xml = @simplexml_load_file(Config::getCons('PATH_CONFIG') . 'filters' . DIRECTORY_SEPARATOR . 'wanted_email.xml');
        } else
            $xml = @simplexml_load_file(Config::getCons('PATH_SYSTEM') . 'data' . DIRECTORY_SEPARATOR . 'wanted_email.xml');

        if (!$xml)
            throw new \Exception('invalid xml file');
        //Check into wanted email list
        for ($i = 0; $i < count($xml->wanted_email); $i++) {
            if ($xml->wanted_email[$i] == $matches[0])
                return true;
        }
        return false;
    }

    public static function isValidCharset($charset, $charsetList = array()) {
        if (!is_string($charset))
            throw new \Exception('Charset must be a string');
        if (!empty($charsetList))
            return (in_array($charset, $charsetList));
        else {
            if (file_exists(Config::getCons('PATH_SYSTEM') . 'data' . DIRECTORY_SEPARATOR . 'Charset.xml')) {
                $charsetList = @simplexml_load_file(Config::getCons('PATH_SYSTEM') . 'data' . DIRECTORY_SEPARATOR . 'Charset.xml');
                foreach ($charsetList as $char) {
                    if ($char == $charset)
                        return true;
                }
                return false;
            }else
                throw new \Exception('Please set charset list data');
        }
    }

    public static function isValidLanguage($language, $languageList = array()) {
        if (!is_string($language))
            throw new \Exception('Language must be a string');
        if (!empty($languageList))
            return (in_array($language, $languageList));
        else {
            if (file_exists(Config::getCons('PATH_SYSTEM') . 'data' . DIRECTORY_SEPARATOR . 'Language.xml')) {
                $languageList = @simplexml_load_file(Config::getCons('PATH_SYSTEM') . 'data' . DIRECTORY_SEPARATOR . 'Language.xml');
                foreach ($languageList as $lang) {
                    if ($lang == $language)
                        return true;
                }
                return false;
            }else
                throw new \Exception('Please set language list data');
        }
    }

    public static function isValidTimeZone($timezone, $timezoneList = array()) {
        if (!is_string($timezone))
            throw new \Exception('Timezone must be a string');
        if (!empty($timezoneList))
            return (in_array($timezone, $timezoneList));
        else {
            if (file_exists(Config::getCons('PATH_SYSTEM') . 'data' . DIRECTORY_SEPARATOR . 'Timezone.xml')) {
                $timezoneList = @simplexml_load_file(Config::getCons('PATH_SYSTEM') . 'data' . DIRECTORY_SEPARATOR . 'Timezone.xml');
                foreach ($timezoneList as $zone) {
                    if ($zone == $timezone)
                        return true;
                }
                return false;
            }else
                throw new \Exception('Please set Timezone list data');
        }
    }

}

?>
